#include "threadstream.h"

ThreadStream::ThreadStream(QLabel *lbl, QObject *parent) : QThread(parent)
{
    this->labelImg = lbl;
    this->source = NULL;
    file = NULL;
    this->pause = false;
    this->record = false;
    this->_size = QSize(640, 480);
    this->release = false;
    this->playMyvideo = false;
    this->SourceCam = false;
}

void ThreadStream::Pause()
{
    this->pause = true;
}

void ThreadStream::StopPause()
{
    pause = false;
}

bool ThreadStream::isPlaying()
{
    return pause;
}

bool ThreadStream::PlayVideo(QString filename)
{
     this->SourceCam = true;
    if (filename.contains(".km"))
    {
        QMediaPlayer *player = new QMediaPlayer;
        player->setMedia(QUrl::fromLocalFile("MySound.mp3"));
        player->setVolume(150);
        player->play();
        qDebug() << player->error();
        this->PlayMyvideo();
        return true;
    }
    this->source = new cv::VideoCapture(filename.toStdString().c_str());
    if (this->source->isOpened())
    {
        pause = false;
        return true;
    }
    qDebug() << "Fail Open Source Filename";
    delete this->source;
    this->source = NULL;
    return false;
}

bool ThreadStream::Abort()
{
    this->release = true;
    return true;
}

bool ThreadStream::PlayCamera()
{
     this->SourceCam = true;
    this->source = new cv::VideoCapture(0);
    if (this->source->isOpened())
    {
        pause = false;
        qDebug() << "Thread run :" << this->isRunning();
        this->start();
        return true;
    }
    qDebug() << "Fail Open Source Camera";
    delete this->source;
    this->source = NULL;
    return false;
}

void ThreadStream::StartRecording()
{
    file = fopen("MyVideo.km", "wb+");
    if (file == NULL)
    {
        qDebug() << "Cant open file ";
        return ;
    }
    this->RGB2YUV = new RGBtoYUV();
    this->dctCompress = new DctCompression(file, 640,  480, 16);
    this->record = true;

    if (this->SourceCam == true)
    {
    this->audioRecorder = new QAudioRecorder;
    QStringList inputs = audioRecorder->audioInputs();

    QAudioEncoderSettings audioSettings;

    audioSettings.setCodec("audio/mp3");
    audioSettings.setQuality(QMultimedia::HighQuality);

    audioRecorder->setEncodingSettings(audioSettings);
    audioRecorder->setOutputLocation(QUrl::fromLocalFile("MySound.mp3"));
    audioRecorder->record();
    }
}

void ThreadStream::StopRecording()
{
    this->audioRecorder->stop();
    this->record = false;
    this->release = true;
}

void ThreadStream::setImgSize(QSize &size)
{
    this->_size = size;
}

void ThreadStream::PlayMyvideo()
{
    while (fopen_s(&readOnly, "MyVideo.km", "rb") != 0)
        qDebug() << "Error opend readOnly File";
    this->RGB2YUV = new RGBtoYUV();
    this->dctCompress = new DctCompression(readOnly, 0,  0, 0);
    playMyvideo = true;
}

void ThreadStream::run()
{
    cv::Mat cameFram;
    forever
    {
        if (this->release == true)
        {
            this->source->release();
            release = false;
        }
        if ((this->pause || this->source == NULL) && playMyvideo != true)
        {
            this->sleep(1);
            continue;
        }
        if (file == NULL && playMyvideo == true)
        {
            QSize sizeLabel = this->_size;
            cv::Mat tmp = this->dctCompress->DCTUnencode();
            tmp = RGB2YUV->ConvertYuv411ToRgb(tmp, tmp.size().width, tmp.size().height);
            QImage img = putImage(tmp);
            QPixmap pix =  QPixmap::fromImage(img);
            pix = pix.scaled(sizeLabel.width(),sizeLabel.height(),Qt::KeepAspectRatio);
            this->labelImg->setPixmap(pix);
            if (readOnly == NULL)
            {
                qDebug() << "readonly close";
                playMyvideo = false;
            }
            continue;
        }
        if (!source->isOpened())
        {
            this->pause = true;
            continue;
        }
        if (!source->grab())
            qDebug() << "Cant Grab frame";
        else
        {

            source->retrieve(cameFram);

            QSize sizeLabel = this->_size;
            CvSize  size = cvSize(640,480);
            cv::Mat tmp(480, 640, cameFram.type());
            cv::resize(cameFram, tmp,size, CV_INTER_LINEAR);
            QImage img = putImage(tmp);
            QPixmap pix =  QPixmap::fromImage(img);
            pix = pix.scaled(sizeLabel.width(),sizeLabel.height(),Qt::KeepAspectRatio);
            if (record == true)
            {
                cv::Mat yuv444 = this->RGB2YUV->ConvertRgbToYuv(tmp);
                cv::Mat yuv411 =  this->RGB2YUV->ConvertYUV_444_To_411(yuv444);
                DCT_ENCODED *tab = this->dctCompress->DCTEncode(yuv411);
            }
            if (record != true && file != NULL)
            {
                fclose(file);
                file = NULL;
            }

            this->labelImg->setPixmap(pix);
        }
    }
}

QImage ThreadStream::putImage(const cv::Mat& mat)
{
    if(mat.type()==CV_8UC1)
    {
        QVector<QRgb> colorTable;
        for (int i=0; i<256; i++)
            colorTable.push_back(qRgb(i,i,i));
        const uchar *qImageBuffer = (const uchar*)mat.data;
        QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_Indexed8);
        img.setColorTable(colorTable);
        return img;
    }

    if(mat.type()==CV_8UC3)
    {
        const uchar *qImageBuffer = (const uchar*)mat.data;
        QImage img(qImageBuffer, mat.cols, mat.rows, mat.step, QImage::Format_RGB888);
        return img.rgbSwapped();
    }
    else
    {
        qDebug() << "ERROR: Mat could not be converted to QImage.";
        return QImage();
    }
}
